/*
   Copyright (c) 2005 Lucas Mello Schnorr <schnorr@gmail.com>
   
   This file is part of DIMVisual.
   
   DIMVisual is free software; you can redistribute it and/or modify it under
   the terms of the GNU Lesser General Public License as published by the
   Free Software Foundation; either version 2 of the License, or (at your
   option) any later version.
   
   DIMVisual is distributed in the hope that it will be useful, but WITHOUT ANY
   WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
   FOR A PARTICULAR PURPOSE.  See the GNU Lesser General Public License
   for more details.
   
   You should have received a copy of the GNU Lesser General Public License
   along with DIMVisual; if not, write to the Free Software Foundation, Inc.,
   59 Temple Place, Suite 330, Boston, MA 02111-1307, USA.
*/
#include "OneToAll.h"

static int key = 0;

@implementation OneToAll
- (id) init
{
	self = [super init];
	operations = [[NSMutableArray alloc] init];
	key = 0;
	return self;
}

- (void) dealloc
{
	[operations release];
	[super dealloc];
}

- (int) searchForMemberEntering: (NSString *) member withKey: (NSString *) myKey
{
	int flag = -1, i;
	for (i = 0; i < [operations count]; i++){
		if ([myKey isEqual: [[operations objectAtIndex: i] objectForKey: @"key"]]){
			if (![[[operations objectAtIndex: i] objectForKey: @"members"] containsObject: member]){
				flag = i;
				break;
			}
		}
	}
	return flag;
}

- (int) searchForMemberExiting: (NSString *) member withKey: (NSString *) myKey
{
	int flag = -1, i;
	for (i = 0; i < [operations count]; i++){
		if ([myKey isEqual: [[operations objectAtIndex: i] objectForKey: @"key"]]){
			if ([[[operations objectAtIndex: i] objectForKey: @"members"] containsObject: member]){
				flag = i;
				break;
			}
		}
	}
	return flag;
}

/* member entering */
- (void) memberEntering: (NSString *) member
	andEventNode: (NSString *) eventNode
	andEventTime: (NSString *) eventTime
	andRootNode: (NSString *) rootNode
	andCommSize: (NSString *) commSize
	andMembersId: (NSString *) membersNode
{
	int flag;
	NSString *myKey;

	myKey = [NSString stringWithFormat: @"%@_%@", membersNode, rootNode];
	
	flag = [self searchForMemberEntering: member withKey: myKey];
	if (flag == -1){
		NSMutableDictionary *x = [[NSMutableDictionary alloc] init];
		NSMutableArray *y = [[NSMutableArray alloc] init];
		[y addObject: member];
		[x setObject: myKey forKey: @"key"];
		[x setObject: y forKey: @"members"];
		[x setObject: commSize forKey: @"size"];
		[x setObject: @"0" forKey: @"consumed"];
		[y release];
		[operations addObject: x];
		flag = [operations indexOfObject: x];
		[x release];
	}else{
		[[[operations objectAtIndex: flag] objectForKey: @"members"] addObject: member];
	}
	if ([rootNode isEqual: eventNode]){
		[[operations objectAtIndex: flag] setObject: member forKey: @"root"];
		[[operations objectAtIndex: flag] setObject: eventTime forKey: @"roottime"];
	}
}

/* member exiting */
- (NSMutableArray *) memberExiting: (NSString *) member
	andEventTime: (NSString *) eventTime
	andOperationName: (NSString *) operName
	andRootNode: (NSString *) rootNode
	andMembersId: (NSString *) membersNode
	andProvider: (id<Integrator>) provider
{
	int flag;
	NSString *myKey;
	NSMutableArray *ret;

	ret = [[NSMutableArray alloc] init];

	myKey = [NSString stringWithFormat: @"%@_%@", membersNode, rootNode];
	flag = [self searchForMemberExiting: member withKey: myKey];
	if (flag == -1){
		/* Error? */
		NSLog (@"flag is -1");
		[ret autorelease];
		return ret;
	}
	
	NSString *root = [[operations objectAtIndex: flag]
		objectForKey: @"root"];
	NSString *roottime = [[operations objectAtIndex: flag]
		objectForKey: @"roottime"];

	if (root == nil || roottime == nil){
		/* Maybe an error? */
		NSLog (@"ERROR, %@(%d)", [operations objectAtIndex: flag],flag);
		exit(1);
	}

	if (![member isEqual: root] && root != nil){
		PajeStartLink *sl;
		sl = [[PajeStartLink alloc] init];
		[sl setTime: roottime];
		[sl setContainer: [provider identifierForEntity: [NSArray arrayWithObjects: @"0", nil] ids: [NSArray arrayWithObjects: @"0", nil]]];
		[sl setSourceContainer: root];
		[sl setEntityType: [provider aliasToName:@"MPICommunication"]];
		[sl setValue: [provider aliasToName: operName]];
		[sl setKey: [NSString stringWithFormat: @"%@%d",operName,key]];

		PajeEndLink *el;
		el = [[PajeEndLink alloc] init];
		[el setTime: eventTime];
		[el setContainer: [provider identifierForEntity: [NSArray arrayWithObjects: @"0", nil] ids: [NSArray arrayWithObjects: @"0", nil]]];
		[el setDestContainer: member];
		[el setEntityType: [provider aliasToName:@"MPICommunication"]];
		[el setValue: [provider aliasToName: operName]];
		[el setKey: [NSString stringWithFormat: @"%@%d",operName,key]];
		
		[ret addObject: sl];
		[ret addObject: el];
		[sl release];
		[el release];

		int consumed = [[[operations objectAtIndex: flag] objectForKey: @"consumed"] intValue];
		consumed++;
		[[operations objectAtIndex: flag] setObject: [NSString stringWithFormat: @"%d", consumed] forKey: @"consumed"];
		if (atoi([[[operations objectAtIndex: flag] objectForKey: @"consumed"] cString]) + 1 == atoi([[[operations objectAtIndex: flag] objectForKey: @"size"] cString])){ /* condition for removal */
			[operations removeObjectAtIndex: flag];
		}
		
		key++;
	}
	[ret autorelease];
	return ret;
}
@end
